﻿using System;
using System.Collections;
using System.Collections.Generic;
using System.Collections.Specialized;
using System.ComponentModel;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace WJP.Domain
{
    /// <summary>
    /// 从这个基类继承来轻松创建一个可序列化、属性变更通知的list类
    /// </summary>
    [Serializable]
    public class SimpleCollection : IList, ICollection, IEnumerable, INotifyCollectionChanged, INotifyPropertyChanged
    {
        #region 属性

        /// <summary>
        /// 集合
        /// </summary>
        protected IList Items { get; }

        #endregion

        #region 构造函数

        /// <summary>
        /// 
        /// </summary>
        public SimpleCollection()
        {
            Items = new ArrayList();
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="list"></param>
        public SimpleCollection(IList list)
        {
            Items = list ?? new ArrayList(); 
        }

        #endregion

        #region 集合操作

        /// <summary>
        /// 获取或设置指定索引处的元素
        /// </summary>
        /// <param name="index">要获取或设置的元素的从零开始的索引</param>
        /// <returns>指定索引处的元素</returns>
        public object this[int index]
        {
            get
            {
                return Items[index];
            }
            set
            {
                SetItem(index, value);
            }
        }

        /// <summary>
        /// 是否只读
        /// </summary>
        public bool IsReadOnly
        {
            get
            {
                return Items.IsReadOnly;
            }
        }

        /// <summary>
        /// 是否具有固定大小
        /// </summary>
        public bool IsFixedSize
        {
            get
            {
                return Items.IsFixedSize;
            }
        }

        /// <summary>
        /// 包含的元素数
        /// </summary>
        public int Count
        {
            get
            {
                return Items.Count;
            }
        }

        /// <summary>
        /// 
        /// </summary>
        public object SyncRoot
        {
            get
            {
                return Items.SyncRoot;
            }
        }

        /// <summary>
        /// 
        /// </summary>
        public bool IsSynchronized
        {
            get
            {
                return Items.IsSynchronized;
            }
        }

        /// <summary>
        /// 将某项添加到集合
        /// </summary>
        /// <param name="value"></param>
        /// <returns></returns>
        public int Add(object value)
        {
            InsertItem(Items.Count, value);
            return Items.Count - 1;
        }

        /// <summary>
        /// 移除所有项
        /// </summary>
        public void Clear()
        {
            ClearItems();
        }

        /// <summary>
        /// 确定集合是否包含特定值
        /// </summary>
        /// <param name="value"></param>
        /// <returns></returns>
        public bool Contains(object value)
        {
            return Items.Contains(value);
        }

        /// <summary>
        /// 从特定的索引处开始，将 System.Array 的元素复制到一个 System.Array
        /// </summary>
        /// <param name="array"></param>
        /// <param name="index"></param>
        public void CopyTo(Array array, int index)
        {
            Items.CopyTo(array, index);
        }

        /// <summary>
        /// 返回循环访问集合的枚举数
        /// </summary>
        /// <returns></returns>
        IEnumerator IEnumerable.GetEnumerator()
        {
            return Items.GetEnumerator();
        }

        /// <summary>
        /// 确定集合中特定项的索引
        /// </summary>
        /// <param name="value"></param>
        /// <returns></returns>
        public int IndexOf(object value)
        {
            return Items.IndexOf(value);
        }

        /// <summary>
        /// 在集合中的指定索引处插入一个项
        /// </summary>
        /// <param name="index"></param>
        /// <param name="value"></param>
        public void Insert(int index, object value)
        {
            InsertItem(index, value);
        }

        /// <summary>
        /// 从集合中移除特定对象的第一个匹配项
        /// </summary>
        /// <param name="value"></param>
        void IList.Remove(object value)
        {
            Remove(value);
        }

        /// <summary>
        /// 移除位于指定索引处的集合项。
        /// </summary>
        /// <param name="index"></param>
        public void RemoveAt(int index)
        {
            RemoveItem(index);
        }

        /// <summary>
        /// 设置指定索引处元素的值
        /// </summary>
        /// <param name="index"></param>
        /// <param name="item"></param>
        protected virtual void SetItem(int index, object item)
        {
            object oldItem = Items[index];
            Items[index] = item;
            OnPropertyChanged("Item[]");
            OnCollectionChanged(NotifyCollectionChangedAction.Replace, item, oldItem, index);
        }

        /// <summary>
        /// 在指定的索引处插入一个项
        /// </summary>
        /// <param name="index"></param>
        /// <param name="item"></param>
        protected virtual void InsertItem(int index, object item)
        {
            Items.Insert(index, item);
            OnPropertyChanged("Count");
            OnPropertyChanged("Item[]");
            OnCollectionChanged(NotifyCollectionChangedAction.Add, item, index);
        }

        /// <summary>
        /// 清除集合
        /// </summary>
        protected virtual void ClearItems()
        {
            Items.Clear();
            OnPropertyChanged("Count");
            OnPropertyChanged("Item[]");
            OnCollectionReset();
        }

        /// <summary>
        /// 从指定索引处移除项
        /// </summary>
        /// <param name="index"></param>
        protected virtual void RemoveItem(int index)
        {
            object obj = Items[index];
            Items.RemoveAt(index);
            OnPropertyChanged("Count");
            OnPropertyChanged("Item[]");
            OnCollectionChanged(NotifyCollectionChangedAction.Remove, obj, index);
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="value"></param>
        /// <returns></returns>
        public virtual bool Remove(object value)
        {
            int index = Items.IndexOf(value);
            if (index < 0)
                return false;
            RemoveItem(index);
            return true;
        }

        /// <summary>
        /// 将元素按指定的索引移动到集合中的新位置
        /// </summary>
        /// <param name="oldIndex"></param>
        /// <param name="newIndex"></param>
        public void Move(int oldIndex, int newIndex)
        {
            MoveItem(oldIndex, newIndex);
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="oldIndex"></param>
        /// <param name="newIndex"></param>
        protected virtual void MoveItem(int oldIndex, int newIndex)
        {
            object obj = Items[oldIndex];
            RemoveItem(oldIndex);
            InsertItem(newIndex, obj);
            OnPropertyChanged("Item[]");
            OnCollectionChanged(NotifyCollectionChangedAction.Move, obj, newIndex, oldIndex);
        }

        #endregion

        #region 属性变更通知

        /// <summary>
        /// 属性变更事件的处理方法
        /// </summary>
        public event PropertyChangedEventHandler PropertyChanged;

        /// <summary>
        /// 
        /// </summary>
        /// <param name="e"></param>
        protected virtual void OnPropertyChanged(PropertyChangedEventArgs e)
        {
            PropertyChanged?.Invoke(this, e);
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="propertyName"></param>
        private void OnPropertyChanged(string propertyName)
        {
            OnPropertyChanged(new PropertyChangedEventArgs(propertyName));
        }

        /// <summary>
        /// 集合变更通知事件的处理方法
        /// </summary>
        public event NotifyCollectionChangedEventHandler CollectionChanged;

        /// <summary>
        /// 
        /// </summary>
        /// <param name="e"></param>
        protected virtual void OnCollectionChanged(NotifyCollectionChangedEventArgs e)
        {
            CollectionChanged?.Invoke(this, e);
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="action">描述导致集合变更事件的操作</param>
        /// <param name="item">受更改影响的项</param>
        /// <param name="index">发生更改处的索引</param>
        private void OnCollectionChanged(NotifyCollectionChangedAction action, object item, int index)
        {
            OnCollectionChanged(new NotifyCollectionChangedEventArgs(action, item, index));
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="action"></param>
        /// <param name="item"></param>
        /// <param name="index"></param>
        /// <param name="oldIndex"></param>
        private void OnCollectionChanged(NotifyCollectionChangedAction action, object item, int index, int oldIndex)
        {
            OnCollectionChanged(new NotifyCollectionChangedEventArgs(action, item, index, oldIndex));
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="action"></param>
        /// <param name="newItem"></param>
        /// <param name="oldItem"></param>
        /// <param name="index"></param>
        private void OnCollectionChanged(NotifyCollectionChangedAction action, object newItem, object oldItem, int index)
        {
            OnCollectionChanged(new NotifyCollectionChangedEventArgs(action, newItem, oldItem, index));
        }

        /// <summary>
        /// 清除集合变更通知
        /// </summary>
        private void OnCollectionReset()
        {
            OnCollectionChanged(new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Reset));
        }

        #endregion
    }
}
